package ca.cbc.giscommon.entity;

import ca.cbc.giscommon.util.StringUtil;
import com.vividsolutions.jts.geom.Geometry;

import javax.persistence.*;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

/**
 * Content is the table store 3rd party feed
 *
 */
@Entity
@Table(name = "event")
public class Event extends BaseEntity implements Cloneable, Serializable {
    private static final long serialVersionUID = -5640566600432135025L;
	private long id;
	/* RSS feed standard tags */
	private String title;
	private String link;
	private String author;
	private String description;
	private Timestamp publishDate;
	/* CBC customized event tags */
	private String audience;
	private String price;
	private String free;
	private Timestamp start;
	private Timestamp end;
	private String locationName;
	private String address;
	private String city;
	private String province;
	private String coordinator;
	private String email;
	private String phone;
	private String company;
	private String eventUrl;
	private String repeats;
	private String postalCode;
	/* Geometry and relationships */
//	private Geometry theGeom;
	private Source source;
	private List<EventSubcategory> eventSubcategories;
	private List<Zone> zones;

	public Event() {}
	
	public Event(String title, String link, String author, String descreption, long publishDate, 
			String audience, String price, String free, long start, long end, String locationName, 
			String address, String city, String province, String coordinator, String email, 
			String phone, String company, String eventUrl, String repeats, String postalCode,
			Source source, Geometry theGeom) {
		this.setTitle(StringUtil.instance.stripTags(title));
		this.setLink(StringUtil.instance.trimIfNotNull(link));
		this.setAuthor(StringUtil.instance.trimIfNotNull(author));
		this.setDescription(StringUtil.instance.stripTags(descreption));
		this.setPublishDate(new Timestamp(publishDate));
		
		this.setAudience(StringUtil.instance.trimIfNotNull(audience));
		this.setPrice(StringUtil.instance.trimIfNotNull(price));
		this.setFree(StringUtil.instance.trimIfNotNull(free));
		this.setStart(new Timestamp(start));
		this.setEnd(new Timestamp(end));
		this.setLocationName(StringUtil.instance.trimIfNotNull(locationName));
		
		this.setAddress(StringUtil.instance.trimIfNotNull(address));
		this.setCity(StringUtil.instance.trimIfNotNull(city));
		this.setProvince(StringUtil.instance.trimIfNotNull(province));
		this.setCoordinator(StringUtil.instance.trimIfNotNull(coordinator));
		this.setEmail(StringUtil.instance.trimIfNotNull(email));
		
		this.setPhone(StringUtil.instance.trimIfNotNull(phone));
		this.setCompany(StringUtil.instance.trimIfNotNull(company));
		this.setEventUrl(StringUtil.instance.trimIfNotNull(eventUrl));
		this.setRepeats(StringUtil.instance.trimIfNotNull(repeats));
		this.setPostalCode(StringUtil.instance.trimIfNotNull(postalCode));
		
		this.setSource(source);
		this.setTheGeom(theGeom);
	}

	public void addEventSubcategory(EventSubcategory eventSubcatgory) {
		if(this.getEventSubcategories() == null) {
			this.eventSubcategories = new ArrayList<EventSubcategory>();
		} 
		
		if(!this.getEventSubcategories().contains(eventSubcatgory)) {
			this.eventSubcategories.add(eventSubcatgory);
		}
	}

	public void addZone(Zone zone) {
		if(this.getZones() == null) {
			this.zones = new ArrayList<Zone>();
		} 
		
		if(!this.getZones().contains(zone)) {
			this.zones.add(zone);
		}
	}

	@Override
	public Event clone() throws CloneNotSupportedException {
		return (Event) super.clone();
	}

	public boolean equals(Object obj) {
		if(obj.getClass().equals(Event.class) && ((Event)obj).getId() == this.getId()) {
			return true;
		}
		return false;
	}
	
	public String getAddress() {
		return address;
	}

	public String getAudience() {
		return audience;
	}

	public String getAuthor() {
		return author;
	}	
	
	public String getCity() {
		return city;
	}

	public String getCompany() {
		return company;
	}

	public String getCoordinator() {
		return coordinator;
	}

	public String getDescription() {
		return description;
	}

	public String getEmail() {
		return email;
	}

	@Column(name = "end_time")
	public Timestamp getEnd() {
		return end;
	}

	@ManyToMany
    @JoinTable(name = "event_event_subcategory",
            joinColumns = {@JoinColumn(name = "event_id")},
            inverseJoinColumns = {@JoinColumn(name = "event_subcategory_id")})
	public List<EventSubcategory> getEventSubcategories() {
		return eventSubcategories;
	}

	@Column(name = "event_url")
	public String getEventUrl() {
		return eventUrl;
	}

	public String getFree() {
		return free;
	}

	@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
	public long getId() {
		return id;
	}

    public String getLink() {
		return link;
	}

    @Column(name = "location_name")
	public String getLocationName() {
		return locationName;
	}

	public String getPhone() {
		return phone;
	}

	@Column(name = "postal_code")
	public String getPostalCode() {
		return postalCode;
	}

	public String getPrice() {
		return price;
	}

	public String getProvince() {
		return province;
	}

	@Column(name = "pubdate")
	public Timestamp getPublishDate() {
		return publishDate;
	}

	public String getRepeats() {
		return repeats;
	}

	@ManyToOne
    @JoinColumn(name = "source_id")
	public Source getSource() {
		return source;
	}

	@Column(name = "start_time")
	public Timestamp getStart() {
		return start;
	}

//	@Column(name = "the_geom")
//	@Type(type = "org.hibernatespatial.GeometryUserType")
//	public Geometry getTheGeom() {
//		return theGeom;
//	}

	public String getTitle() {
		return title;
	}

	@Transient
	public List<Zone> getZones() {
		return zones;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public void setAudience(String audience) {
		this.audience = audience;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public void setCity(String city) {
		this.city = city;
	}

	public void setCompany(String company) {
		this.company = company;
	}

	public void setCoordinator(String coordinator) {
		this.coordinator = coordinator;
	}

	public void setDescription(String description) {
		this.description = description;
	}
	
	public void setEmail(String email) {
		this.email = email;
	}
	
	public void setEnd(Timestamp end) {
		this.end = end;
	}

	public void setEventSubcategories(List<EventSubcategory> eventSubcategories) {
		this.eventSubcategories = eventSubcategories;
	}

	public void setEventUrl(String eventUrl) {
		this.eventUrl = eventUrl;
	}

	public void setFree(String free) {
		this.free = free;
	}

	public void setId(long id) {
		this.id = id;
	}

	public void setLink(String link) {
		this.link = link;
	}

	public void setLocationName(String locationName) {
		this.locationName = locationName;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	public void setPostalCode(String postalCode) {
		this.postalCode = postalCode;
	}

	public void setPrice(String price) {
		this.price = price;
	}

	public void setProvince(String province) {
		this.province = province;
	}
	
    public void setPublishDate(Timestamp publishDate) {
		this.publishDate = publishDate;
	}
    
    public void setRepeats(String repeats) {
		this.repeats = repeats;
	}
    
    public void setSource(Source source) {
		this.source = source;
	}

    public void setStart(Timestamp start) {
		this.start = start;
	}

//	public void setTheGeom(Geometry theGeom) {
//		this.theGeom = theGeom;
//	}

	public void setTitle(String title) {
		this.title = title;
	}
	
	public void setZones(List<Zone> zones) {
		this.zones = zones;
	}

	public String toString() {
		StringBuilder zonesSB = null;
		if(zones != null) {
			zonesSB = new StringBuilder("{");
			for(Zone zone : zones) {
				zonesSB.append(zone.toString()).append(", ");
			}
			zonesSB.delete(zonesSB.length()-2, zonesSB.length()).append("}");
		}
		
		StringBuilder eventTypesSB = null;
		if(eventSubcategories != null) {
			eventTypesSB = new StringBuilder("{");
			for(EventSubcategory et : eventSubcategories) {
				eventTypesSB.append(et.toString()).append(", ");
			}
			eventTypesSB.delete(eventTypesSB.length()-2, eventTypesSB.length()).append("}");
		}
		
    	StringBuilder sf = new StringBuilder();
    	sf.append("Event {id: ").append(id)
    	  .append(", title:").append(title)
    	  .append(", link:").append(link)
    	  .append(", publishDate:").append(publishDate)
    	  .append(", locationName:").append(locationName)
    	  .append(", postalCode:").append(postalCode)
    	  .append(", start:").append(start)
    	  .append(", end:").append(end)
    	  .append(", price:").append(price)
    	  .append(", eventUrl:").append(eventUrl)
    	  .append(", eventSubcategories:").append(eventTypesSB == null ? null : eventTypesSB.toString())
    	  .append(", source:").append(source)
    	  .append(", zones:").append(zonesSB == null ? null : zonesSB.toString())
    	  .append(", theGome:").append(theGeom)
    	  .append("}");
    	
    	return sf.toString();
    }
}
